/**
 * @file    app_command_process.c
 * @author  yhy
 * @brief   指令处理模块
 * @version 1.00
 * @date    2025-07-26
 *
 * @copyright Copyright (c) 2025
 *
 */
#include "app_command_process.h"

#include "app_all_airbag.h"
#include "app_communication.h"
#include "app_flank.h"
#include "app_hip.h"
#include "app_lumbar.h"
#include "app_massage.h"
#include "app_thigh.h"
#include "app_vent_heat.h"
#include "common_debug.h"

#include <string.h>

static result_e app_command_process_lumbar_handler(control_cmd_id_e cmd_id, uint8_t command_value);
static result_e app_command_process_massage_handler(control_cmd_id_e cmd_id, uint8_t command_value);
static result_e app_command_process_flank_handler(control_cmd_id_e cmd_id, uint8_t command_value);
static result_e app_command_process_thigh_handler(control_cmd_id_e cmd_id, uint8_t command_value);
static result_e app_command_process_hip_handler(control_cmd_id_e cmd_id, uint8_t command_value);
static result_e app_command_process_vent_heat_handler(control_cmd_id_e cmd_id, uint8_t command_value);
static result_e app_command_process_all_airbag_handler(control_cmd_id_e cmd_id, uint8_t command_value);

static control_signal_type_e app_command_process_check_signal_validity(control_cmd_id_e cmd_id,
                                                                       uint8_t          current_value,
                                                                       uint8_t         *last_value);
static void                  app_command_process_extract_commands_from_can(void);
static void                  app_command_process_process_commands(void);
static result_e              app_command_process_execute_command(control_command_t *command);

/* 控制指令映射表 */
static control_cmd_map_t control_cmd_map[CONTROL_CMD_ID_MAX] = {
    /* 腰托 */
    { CONTROL_CMD_ID_DR_LUMBAR_F_R_MANUAL_CTRL, "DR lumbar support forward back manual adjust",
      app_command_process_lumbar_handler, true },
    { CONTROL_CMD_ID_DR_LUMBAR_U_D_MANUAL_CTRL, "DR lumbar support up down manual adjust",
      app_command_process_lumbar_handler, true },
    /* 按摩 */
    { CONTROL_CMD_ID_DR_MASSAGE_MODE_CTRL, "DR massage mode manual adjust",
      app_command_process_massage_handler, true },
    { CONTROL_CMD_ID_DR_MASSAGE_INTENSITY_CTRL, "DR massage intensity manual adjust",
      app_command_process_massage_handler, true },
    { CONTROL_CMD_ID_DR_MASSAGE_TIME_CTRL, "DR massage time manual adjust",
      app_command_process_massage_handler, true },
    { CONTROL_CMD_ID_DR_MASSAGE_SWITCH_CTRL, "DR massage switch manual adjust",
      app_command_process_massage_handler, true },
    /* 侧翼 */
    { CONTROL_CMD_ID_DR_FLANK_MODE_CTRL, "DR flank mode manual adjust", app_command_process_flank_handler,
      true },
    /* 腿托 */
    { CONTROL_CMD_ID_DR_THIGH_MODE_CTRL, "DR thigh mode manual adjust", app_command_process_thigh_handler,
      true },
    /* 臀部 */
    { CONTROL_CMD_ID_DR_HIP_UP_CTRL, "DR hip up manual adjust", app_command_process_hip_handler, true },
    { CONTROL_CMD_ID_DR_HIP_DOWN_CTRL, "DR hip down manual adjust", app_command_process_hip_handler, true },
    /* 通风加热 */
    { CONTROL_CMD_ID_DR_VENT_HEAT_MODE_CTRL, "DR vent heat mode manual adjust",
      app_command_process_vent_heat_handler, true },
    /* 气袋全开全关 */
    { CONTROL_CMD_ID_DR_ALL_AIRBAG_CTRL, "DR all airbag switch manual adjust",
      app_command_process_all_airbag_handler, true },
};

/* 控制指令缓存 */
static control_command_t control_commands[CONTROL_CMD_ID_MAX];

/* 首次运行标志 */
static bool first_run = true;

/* 按摩系统上次开关状态，用于检测按摩开关状态变化 */
static bool last_massage_switch_state = false;

/**
 * @brief 初始化指令处理模块
 */
void app_command_process_init(void)
{
    /* 初始化控制指令缓存 */
    for (uint8_t i = 0; i < CONTROL_CMD_ID_MAX; ++i) {
        control_commands[i].cmd_id        = (control_cmd_id_e)i;
        control_commands[i].current_value = 0;
        control_commands[i].last_value    = 0;
        control_commands[i].value_changed = false;
        control_commands[i].enabled       = true;
    }

    first_run                 = true;
    last_massage_switch_state = false;
    LOG("Command process initialized successfully\n");
}

/**
 * @brief 指令处理调度函数, 放在调度器中循环调度
 *
 */
void app_command_process_handle(void)
{
    /* 从CAN数据中提取控制指令 */
    app_command_process_extract_commands_from_can();

    /* 处理控制指令 */
    app_command_process_process_commands();
}

/**
 * @brief 从CAN数据结构体中提取控制指令
 *
 */
static void app_command_process_extract_commands_from_can(void)
{
    /* 腰托手动调节指令 */
    control_commands[CONTROL_CMD_ID_DR_LUMBAR_F_R_MANUAL_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_lumbar_f_r_manual_request_pneumatic;
    control_commands[CONTROL_CMD_ID_DR_LUMBAR_U_D_MANUAL_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_lumbar_u_d_manual_request_pneumatic;

    /* 按摩手动调节指令  */
    control_commands[CONTROL_CMD_ID_DR_MASSAGE_MODE_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_massage_mode_request_pneumatic;
    control_commands[CONTROL_CMD_ID_DR_MASSAGE_INTENSITY_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_massage_intensity_request_pneumatic;
    control_commands[CONTROL_CMD_ID_DR_MASSAGE_TIME_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_massage_time_request_pneumatic;
    control_commands[CONTROL_CMD_ID_DR_MASSAGE_SWITCH_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_massage_switch_request_pneumatic;

    /* 侧翼手动调节指令 */
    control_commands[CONTROL_CMD_ID_DR_FLANK_MODE_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_bolstersupport_manual_request_pneumatic;

    /* 腿托手动调节指令 */
    control_commands[CONTROL_CMD_ID_DR_THIGH_MODE_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_thighsupport_manual_request_pneumatic;

    /* 臀部手动调节指令 */
    control_commands[CONTROL_CMD_ID_DR_HIP_UP_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_highsupport_manual_request_up_pneumatic;
    control_commands[CONTROL_CMD_ID_DR_HIP_DOWN_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_highsupport_manual_request_down_pneumatic;

    /* 通风加热模式手动调节指令 */
    control_commands[CONTROL_CMD_ID_DR_VENT_HEAT_MODE_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_heater_cooler_sw_pneumatic;

    /* TODO： ALL airbag test */
    control_commands[CONTROL_CMD_ID_DR_ALL_AIRBAG_CTRL].current_value =
        hvs_fl_req1.can_data_u.signal.dr_showroom_state_sps;
}

/**
 * @brief 处理所有控制命令
 *
 */
static void app_command_process_process_commands(void)
{
    for (uint8_t i = 0; i < CONTROL_CMD_ID_MAX; ++i) {

        control_command_t *command = &control_commands[i];

        /* 检查指令是否启用 */
        if (!command->enabled) {
            continue;
        }

        /* 检查信号有效性和变化 */
        control_signal_type_e signal_type = app_command_process_check_signal_validity(
            command->cmd_id, command->current_value, &command->last_value);

        if (signal_type == CONTROL_SIGNAL_TYPE_VALID) {
            command->value_changed = true;
            /* 执行控制指令 */
            result_e result        = app_command_process_execute_command(command);
            if (result != RESULT_STATUS_OK) {
                LOG("Failed to execute command %s, error: %u\n", control_cmd_map[i].cmd_name, result);
            }
        }
        else if (signal_type == CONTROL_SIGNAL_TYPE_UNCHANGE) {
            command->value_changed = false;
            /* 信号为变化, 不执行操作 */
        }
        else {
            /* 信号无效, 不执行操作 */
            command->value_changed = false;
        }
    }
}

/**
 * @brief 检查信号有效性和变化
 *
 * @param cmd_id                    控制命令ID
 * @param current_value             当前信号值
 * @param last_value                上一次信号值
 * @return control_signal_type_e    信号类型
 */
static control_signal_type_e app_command_process_check_signal_validity(control_cmd_id_e cmd_id,
                                                                       uint8_t          current_value,
                                                                       uint8_t         *last_value)
{
    /* 通风加热模块特殊处理：0是有效的OFF指令 */
    if (cmd_id == CONTROL_CMD_ID_DR_VENT_HEAT_MODE_CTRL) {
        /* 对于通风加热，0-6都是有效值 */
        if (current_value > VENT_HEAT_MODE_HI_COOL) {
            return CONTROL_SIGNAL_TYPE_INVALID;
        }
    }
    else {
        /* 其他模块：检查是否为无效帧 */
        if (current_value == CONTROL_SIGNAL_TYPE_INVALID) {
            return CONTROL_SIGNAL_TYPE_INVALID;
        }
    }

    /* 首次运行, 认为是有效信号 */
    if (first_run) {
        *last_value = current_value;
        first_run   = false;
        return CONTROL_SIGNAL_TYPE_VALID;
    }

    /* 按摩模式特殊处理：当按摩系统从关闭变为开启时，即使模式值相同也认为是有效信号 */
    if (cmd_id == CONTROL_CMD_ID_DR_MASSAGE_MODE_CTRL) {
        bool current_massage_switch_state = massage_system.is_open;

        /* 检查按摩开关状态是否从关闭变为开启 */
        if (!last_massage_switch_state && current_massage_switch_state) {
            /* 按摩系统刚刚开启，即使模式值相同也认为是有效信号 */
            *last_value               = current_value;
            last_massage_switch_state = current_massage_switch_state;
            return CONTROL_SIGNAL_TYPE_VALID;
        }

        /* 更新按摩开关状态记录 */
        last_massage_switch_state = current_massage_switch_state;
    }

    /* 检查值是否发送变化 */
    if (current_value != *last_value) {
        *last_value = current_value;
        return CONTROL_SIGNAL_TYPE_VALID;
    }

    /* 信号未发送变化, 认为是无效信号 */
    return CONTROL_SIGNAL_TYPE_UNCHANGE;
}

/**
 * @brief 指令控制命令
 *
 * @param   command     控制指令
 * @return  result_e    执行结果, RESULT_STATUS_OK 表示成功, 其他值表示失败
 */
static result_e app_command_process_execute_command(control_command_t *command)
{
    if (command->cmd_id >= CONTROL_CMD_ID_MAX) {
        return RESULT_STATUS_INVALID_PARAM;
    }

    control_cmd_map_t *cmd_map = &control_cmd_map[command->cmd_id];

    /* 检查处理器是否启用 */
    if (!cmd_map->enabled) {
        return RESULT_STATUS_OK; /* 直接返回, 被禁用改命令执行函数, 并不是错误 */
    }

    /* 检查处理函数是否存在 */
    if (!cmd_map->handler_func) {
        LOG("No handler function for command %s\n", cmd_map->cmd_name);
        return RESULT_STATUS_NOT_IMPLEMENTED;
    }

    /* 调用处理函数 */
    LOG("Execute command %s with value: %u\n", cmd_map->cmd_name, command->current_value);
    return cmd_map->handler_func(command->cmd_id, command->current_value);
}

/**
 * @brief 全气袋处理函数
 *
 * @param cmd_id
 * @param command_value
 * @return result_e
 */
static result_e app_command_process_all_airbag_handler(control_cmd_id_e cmd_id, uint8_t command_value)
{
    result_e result = RESULT_STATUS_OK;
    switch (cmd_id) {
    case CONTROL_CMD_ID_DR_ALL_AIRBAG_CTRL:
        result = app_all_airbag_set_mode((all_airbag_mode_e)command_value);
        break;
    }

    return result;
}

/**
 * @brief 通风加热模式手动调节指令处理函数
 *
 * @param   cmd_id          控制命令ID
 * @param   command_value   控制命令值
 * @return  result_e        执行结果, RESULT_STATUS_OK 表示成功, 其他值表示失败
 */
static result_e app_command_process_vent_heat_handler(control_cmd_id_e cmd_id, uint8_t command_value)
{
    result_e result = RESULT_STATUS_OK;

    switch (cmd_id) {
    case CONTROL_CMD_ID_DR_VENT_HEAT_MODE_CTRL:
        result = app_vent_heat_set_mode((vent_heat_mode_e)command_value);
        break;
    }

    return result;
}

/**
 * @brief 臀部控制命令处理函数
 *
 * @param cmd_id            控制命令ID
 * @param command_value     控制命令值
 * @return result_e         执行结果, RESULT_STATUS_OK 表示成功, 其他值表示失败
 */
static result_e app_command_process_hip_handler(control_cmd_id_e cmd_id, uint8_t command_value)
{
    result_e result = RESULT_STATUS_OK;

    switch (cmd_id) {
    case CONTROL_CMD_ID_DR_HIP_UP_CTRL:   result = app_hip_set_mode((hip_mode_e)command_value); break;
    case CONTROL_CMD_ID_DR_HIP_DOWN_CTRL: result = app_hip_set_mode((hip_mode_e)(command_value + 3)); break;
    }

    return result;
}

/**
 * @brief 腿托控制命令处理函数
 *
 * @param cmd_id            控制命令ID
 * @param command_value     控制命令值
 * @return result_e         执行结果, RESULT_STATUS_OK 表示成功, 其他值表示失败
 */
static result_e app_command_process_thigh_handler(control_cmd_id_e cmd_id, uint8_t command_value)
{
    result_e result = RESULT_STATUS_OK;

    switch (cmd_id) {
    case CONTROL_CMD_ID_DR_THIGH_MODE_CTRL: result = app_thigh_set_mode((thigh_mode_e)command_value); break;
    }

    return result;
}

/**
 * @brief 侧翼控制命令处理函数
 *
 * @param cmd_id            控制命令ID
 * @param command_value     控制命令值
 * @return result_e         执行结果, RESULT_STATUS_OK 表示成功, 其他值表示失败
 */
static result_e app_command_process_flank_handler(control_cmd_id_e cmd_id, uint8_t command_value)
{
    result_e result = RESULT_STATUS_OK;
    switch (cmd_id) {
    case CONTROL_CMD_ID_DR_FLANK_MODE_CTRL: result = app_flank_set_mode((flank_mode_e)command_value); break;
    }

    return result;
}

/**
 * @brief 按摩控制命令处理函数
 *
 * @param cmd_id            控制命令ID
 * @param command_value     控制命令值
 * @return result_e         执行结果, RESULT_STATUS_OK 表示成功, 其他值表示失败
 */
static result_e app_command_process_massage_handler(control_cmd_id_e cmd_id, uint8_t command_value)
{
    result_e result = RESULT_STATUS_OK;

    switch (cmd_id) {
    case CONTROL_CMD_ID_DR_MASSAGE_MODE_CTRL: // 按摩模式手动调节
        if (massage_system.state == MASSAGE_STATE_RUNNING) {
            result = app_massage_set_mode((massage_mode_e)command_value);
        }
        else {
            result = app_massage_start((massage_mode_e)command_value, massage_system.current_intensity);
        }
        break;

    case CONTROL_CMD_ID_DR_MASSAGE_INTENSITY_CTRL: // 按摩强度手动调节
        result = app_massage_set_intensity((massage_intensity_e)command_value);
        break;

    case CONTROL_CMD_ID_DR_MASSAGE_TIME_CTRL: // 按摩时间手动调节
        result = app_massage_set_max_time((massage_time_e)command_value);
        break;

    case CONTROL_CMD_ID_DR_MASSAGE_SWITCH_CTRL: // 按摩开关手动调节
        switch (command_value) {
        case MASSAGE_SWITCH_STATE_ON: app_massage_switch(true); break;
        case MASSAGE_SWITCH_STATE_OFF:
            app_massage_switch(false);
            result = app_massage_stop();
            break;
        }
        break;
    }

    return result;
}

/**
 * @brief 处理腿托系统控制命令处理函数
 *
 * @param cmd_id            控制命令ID
 * @param command_value     控制命令值
 * @return result_e         执行结果, RESULT_STATUS_OK 表示成功, 其他值表示失败
 */
static result_e app_command_process_lumbar_handler(control_cmd_id_e cmd_id, uint8_t command_value)
{
    lumbar_mode_e mode = LUMBAR_MODE_F_R_KEEP;

    switch (cmd_id) {
    case CONTROL_CMD_ID_DR_LUMBAR_F_R_MANUAL_CTRL:
        switch (command_value) {
        case LUMBAR_F_R_STATE_MOVE_FRONT: mode = LUMBAR_MODE_FRONT; break; // move front
        case LUMBAR_F_R_STATE_MOVE_REAR:  mode = LUMBAR_MODE_REAR; break;  // move rear
        case LUMBAR_F_R_STATE_KEEP:       mode = LUMBAR_MODE_F_R_KEEP; break;    // keep
        }
        break;
    case CONTROL_CMD_ID_DR_LUMBAR_U_D_MANUAL_CTRL:
        switch (command_value) {
        case LUMBAR_U_D_STATE_MOVE_UP:   mode = LUMBAR_MODE_UP; break;   // move up
        case LUMBAR_U_D_STATE_MOVE_DOWN: mode = LUMBAR_MODE_DOWN; break; // move down
        case LUMBAR_U_D_STATE_KEEP:      mode = LUMBAR_MODE_U_D_KEEP; break;  // keep
        }
        break;
    }

    return app_lumbar_set_mode(mode);
}
